package com.douqu.game.main.util;

import com.douqu.game.core.config.StableDataConfig;
import com.douqu.game.core.config.common.CommonData;
import com.douqu.game.core.config.common.GoodsData;
import com.douqu.game.core.controller.PlayerController;
import com.douqu.game.core.e.*;
import com.douqu.game.core.entity.Player;
import com.douqu.game.core.entity.battle.BattleDetail;
import com.douqu.game.core.entity.battle.BattleInitParamWorldMap;
import com.douqu.game.core.entity.battle.BattleTemp;
import com.douqu.game.core.entity.battle.SpriteTemp;
import com.douqu.game.core.entity.common.TwoTuple;
import com.douqu.game.core.entity.ext.BagInfo;
import com.douqu.game.core.entity.ext.SettingInfo;
import com.douqu.game.core.entity.ext.data.boon.AutoRecover;
import com.douqu.game.core.entity.ext.data.challenge.HegemonyScoreChangeBean;
import com.douqu.game.core.entity.ext.data.challenge.WorldMapBeKillBean;
import com.douqu.game.core.entity.ext.data.challenge.WorldMapTaskData;
import com.douqu.game.core.entity.world.map.*;
import com.douqu.game.core.factory.ConfigFactory;
import com.douqu.game.core.factory.ConstantFactory;
import com.douqu.game.core.factory.DataFactory;
import com.douqu.game.core.factory.SevenDayFactory;
import com.douqu.game.core.factory.WorldInfoFactory;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.util.CoreUtils;
import com.douqu.game.core.util.LogUtils;
import com.douqu.game.core.util.SendUtils;
import com.douqu.game.main.GameServer;
import com.douqu.game.main.server.RecordManager;
import com.douqu.game.main.server.ServerManager;
import com.douqu.game.main.server.WorldManager;
import com.douqu.game.main.server.entity.ServerInfoBattle;

import java.util.List;
import java.util.Map;

/**
 * @Author: Bean
 * @Description:
 * @Date: 2018-05-23 16:33
 */
public class WorldMapUtils {


    public static BattleTemp createBattleTemp(Player player, double masterHPRate, double armyHPRate)
    {
        return new BattleTemp(player, masterHPRate, armyHPRate);
    }

    public static BattleTemp createBattleTemp(SpriteGarrisonBean spriteGarrisonBean)
    {
        return new BattleTemp(spriteGarrisonBean);
    }


    public static void directEndMapBattle(SpriteBean source, SpriteBean target, int cityId, List<Player> saveOfflinePlayerList)
    {
        WorldMapData worldMapData = WorldInfoFactory.getInstance().getWorldMapData(source.getMasterPlayerIndex());
        CityBean cityBean = worldMapData.getCity(cityId);
        if(cityBean == null)
        {
            LogUtils.error("城不存在 -> " + cityId);
            return;
        }

        ServerInfoBattle serverInfo = ServerManager.getInstance().getFreeBattleServer();
        if(serverInfo == null)
        {
            LogUtils.warn("大地图战斗直接结算 -> source:" + source + " target:" + target);
            SpriteBean winner = null, loser = null;
            if(source.getBaseInfo().getFc() > target.getBaseInfo().getFc())
            {
                winner = source;
                loser = target;
            }
            else
            {
                winner = target;
                loser = source;
            }

            BattleTemp winnerBattleTemp = winner.getBattleTemp();

            double rate = (double)loser.getBaseInfo().getFc() / winner.getBaseInfo().getFc();
            rate = Math.pow(rate, 2);
            winnerBattleTemp.getMaster().addHPByRate(-rate);
            for(SpriteTemp spriteTemp : winnerBattleTemp.getSoldierList())
            {
                spriteTemp.addHPByRate(-rate);
            }
            if(winnerBattleTemp.getMaster().getHp() <= 0)
            {
                winnerBattleTemp.getMaster().setHp(10);
            }

            battleEnd(null, winner, loser, cityBean, E_BattleDetailType.DATA_WORLD_MAP_DIRECT_END.getCode(), winnerBattleTemp, loser.getBattleTemp(), saveOfflinePlayerList);
        }
        else
        {
            E_BattleDetailType battleDetailType = null;
            if(source instanceof SpritePlayerBean)
            {
                if(target instanceof SpritePlayerBean)
                    battleDetailType = E_BattleDetailType.DATA_WORLD_MAP_PVP;
                else if(target instanceof SpriteGarrisonBean)
                    battleDetailType = E_BattleDetailType.DATA_WORLD_MAP_PVG;
                else if(target instanceof SpriteExpeditionBean)
                    battleDetailType = E_BattleDetailType.DATA_WORLD_MAP_PVE;
            }
            else if(source instanceof SpriteExpeditionBean)
            {
                if(target instanceof SpriteGarrisonBean)
                    battleDetailType = E_BattleDetailType.DATA_WORLD_MAP_EVG;
                else if(target instanceof SpriteExpeditionBean)
                    battleDetailType = E_BattleDetailType.DATA_WORLD_MAP_EVE;
            }

            if(battleDetailType != null)
            {
                int mapId = DataFactory.getInstance().getMapIdByWorldMap(cityBean.camp);

                BattleInitParamWorldMap temp = new BattleInitParamWorldMap(mapId, cityBean.id, source.getMasterPlayerIndex());

                String battleId = CoreUtils.createBattleId(source.getObjectIndex(), target.getObjectIndex());

                serverInfo.sendBattleInit(battleId, SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_WORLD_MAP_VALUE, battleDetailType.getCode(), source.getObjectIndex(), target.getObjectIndex(), temp);

                BattleDetail battleDetail = new BattleDetail(0, temp);
                battleDetail.setId(battleId);
                serverInfo.addBattle(battleDetail);

                RecordManager.getInstance().addWorldMapBattleStartRecord(battleId, source, target, cityId, battleDetailType);
            }
        }

    }


    public static void battleEnd(String battleId, SpriteBean winner, SpriteBean loser, CityBean cityBean, int battleDetailType, BattleTemp winnerBattleTemp, BattleTemp loserBattleTemp, List<Player> offlinePlayerList)
    {
        if(winner != null)
        {
            if(winner.isAttacker())
                MsgUtils.sendMapBattleReport(cityBean, winner, loser, winner.getObjectIndex());
            else if(winner.isDefender())
                MsgUtils.sendMapBattleReport(cityBean, loser, winner, winner.getObjectIndex());
        }

        cityBean.leave(loser, winner, E_CityInOutType.OUT_BATTLE);

        LogUtils.debug("当前城的状态 -> " + cityBean);

        if(winner != null)
        {
            winner.updateBattleTemp(winnerBattleTemp);

            if(winner instanceof SpritePlayerBean)
            {
                Player winPlayer = ((SpritePlayerBean) winner).getPlayer();
                if(winPlayer != null)//Player不为空
                {
                    CommonData[] commonDatas = new CommonData[]{
                            new CommonData(SGCommonProto.E_WORLDMAPTASK_TYPE.WORLD_MAP_TASK_KILL_GENERAL.getNumber(),1),
                            new CommonData(SGCommonProto.E_WORLDMAPTASK_TYPE.WORLD_MAP_TASK_KILL_CARD.getNumber(), (int) winnerBattleTemp.getTotalDamage())};

                    WorldManager.updateWorldMapTaskComplete(winPlayer, commonDatas);

                    //-1 表示是机器人
                    int loserCount = -1;
                    if(loser instanceof SpritePlayerBean)
                    {
                        Player losePlayer = ((SpritePlayerBean) loser).getPlayer();
                        if(losePlayer != null) loserCount = losePlayer.getWorldMapKillData().getSkillCount();
                    }

                    WorldMapData worldMapData = WorldInfoFactory.getInstance().getWorldMapData(winner.getMasterPlayerIndex());
                    HegemonyScoreChangeBean changeBean = null;
                    if (worldMapData != null && worldMapData.hegemonyIsSettle(winPlayer)){
                        WorldMapBeKillBean mapBeKillBean = new WorldMapBeKillBean(loser.getObjectIndex(),loser.getName(), loser.getBaseInfo().getLv(),loserCount);
                         changeBean = winPlayer.getWorldMapTaskData().battleResult(mapBeKillBean, true, winner.getMasterPlayerIndex());
                    }

                    PlayerController playerController = ((SpritePlayerBean) winner).getPlayerController();

                    // 自动回血
                    checkAutoRecover(winPlayer, winnerBattleTemp, playerController);

                    if(playerController == null)
                    {
                        offlinePlayerList.add(winPlayer);
                    }
                    else
                    {
                        playerController.setLastUpdate(DataFactory.currentTime, 0, E_PlayerLastUpdate.BATTLE_END_MAP);
                        playerController.clearBattle();

                        // 推送血量更新
                        SendUtils.sendWorldMapHPUpdate(playerController);

                        if(playerController.getTcpConnection() == null){

                            playerController.setWorldMapTaskCacheData(commonDatas);
                            if (changeBean != null)
                                playerController.setHegemonyScoreChangeBeanCache(changeBean);
                        }
                        else{
                            MsgUtils.sendWorldMapTaskChange(playerController, commonDatas);
                            //推送争霸赛积分变化
                            if (changeBean != null)
                                SendUtils.sendHegemoneyChange(playerController, changeBean);

                            SendUtils.sendChangeData(0, playerController);
                        }
                        //检测开服活动是否完成
                        if (winner.isAttacker())
                        winPlayer.getSevenDayData().checkAllRewardState(SevenDayFactory.EVENT_TYPE_15,1);
                    }
                }
            }
        }

        if(loser != null)
        {
            loserBattleTemp.die();
            loser.updateBattleTemp(loserBattleTemp);

            if(loser instanceof SpritePlayerBean)
            {
                Player losePlayer = ((SpritePlayerBean) loser).getPlayer();
                if(losePlayer != null)//Player不为空
                {
                    CommonData commonData = null;
                    if(loserBattleTemp != null)
                    {
                        commonData = new CommonData(SGCommonProto.E_WORLDMAPTASK_TYPE.WORLD_MAP_TASK_KILL_CARD.getNumber(), (int) loserBattleTemp.getTotalDamage());
                        WorldManager.updateWorldMapTaskComplete(losePlayer, commonData);
                    }
                    commonData = new CommonData(SGCommonProto.E_WORLDMAPTASK_TYPE.WORLD_MAP_TASK_KILL_CARD.getNumber(), (int) loserBattleTemp.getTotalDamage());
                    WorldManager.updateWorldMapTaskComplete(losePlayer, commonData);

                    PlayerController playerController = ((SpritePlayerBean) loser).getPlayerController();
                    if(playerController == null)
                    {
                        hegemonyLose((SpritePlayerBean) loser);
                        offlinePlayerList.add(losePlayer);
                    }
                    else
                    {
                        SendUtils.sendWorldMapHPUpdate(playerController);

                        playerController.setLastUpdate(DataFactory.currentTime, 0, E_PlayerLastUpdate.BATTLE_END_MAP);
                        playerController.clearBattle();

                        if(commonData != null)
                        {
                            if(playerController.getTcpConnection() == null)
                                playerController.setWorldMapTaskCacheData(commonData);
                            else
                            {
                                MsgUtils.sendWorldMapTaskChange(playerController, commonData);
                                SendUtils.sendChangeData(0, playerController);
                            }
                        }
                    }
                    //检测开服活动是否完成
                    if (winner.isAttacker())
                        losePlayer.getSevenDayData().checkAllRewardState(SevenDayFactory.EVENT_TYPE_15,1);
                }
            }
        }

        RecordManager.getInstance().addWorldMapBattleEndRecord(battleId, winner, loser, cityBean, battleDetailType);

        LogUtils.debug("winner -> " + winnerBattleTemp);
        LogUtils.debug("loser -> " + loserBattleTemp);
    }

    public static void initRecover(SpritePlayerBean spritePlayerBean, boolean lose)
    {
        spritePlayerBean.stop();
        if(!spritePlayerBean.getBattleTemp().isFull())
        {
            spritePlayerBean.setStatus(SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_RECOVER);
            RecoverParam recoverParam = new RecoverParam(spritePlayerBean.getBattleTemp(), ConfigFactory.WORLD_MAP_STATUS_WAIT_TIME/1000);
            spritePlayerBean.setRecoverParam(recoverParam);

            Player player = spritePlayerBean.getPlayer();
            if(player != null)
            {
                if (lose){
                    hegemonyLose(spritePlayerBean);
                }else{
                    LogUtils.error(player.name + "lose 为false 不结算");
                }

                if (spritePlayerBean.getPlayerController() == null){
                    //玩家不在线
                    GameServer.getInstance().savePlayer(player);
                    spritePlayerBean.getBattleTemp().full();
                }
            }
        }

    }


    /**
     * 争霸赛lose
     */
    public static void hegemonyLose(SpritePlayerBean spritePlayerBean)
    {
        //获取当前小时
        WorldMapData mapData =  WorldInfoFactory.getInstance().getWorldMapData(spritePlayerBean.getMasterPlayerIndex());

        /**
         * 不在结算时间内不结算
         */
        Player player = spritePlayerBean.getPlayer();
        if (player == null){
            LogUtils.error( "玩家不存在 不能进行结算");
            return;
        }

        //当进行结算的时候清除玩家的道具使用记录
        player.getExtInfo(SettingInfo.class).getAutoRecover().clearItemTimes();

        WorldMapTaskData worldMapTaskData = player.getWorldMapTaskData();
        if (!mapData.hegemonyIsSettle(player)){
            worldMapTaskData.getKillData().initCurrent();
            LogUtils.error( "结算时间与等级不正确");
            return;
        }
        if (worldMapTaskData.getKillData().getSkillCount() == 0){
            LogUtils.error( "玩家连杀次数为0 不结算");
            return;
        }
        int beforeValue = worldMapTaskData.getKillData().getMaxValue(E_WorldMapKillRankType.CURRENT_WEEK_RANK);
        worldMapTaskData.battleResult(null, false, spritePlayerBean.getMasterPlayerIndex());
        TwoTuple<Map<SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE,SGCommonProto.HegemonyResultItem.Builder>,Boolean> settleTwo = worldMapTaskData.getKillData().getSettleInfo();

        if (spritePlayerBean.getPlayerController() != null && spritePlayerBean.getActionPlayerType() == E_ActionPlayerType.ONLINE_MAP){
            /**
             * 连杀数大于1 且玩家在线才会弹出结算
             */

            if (worldMapTaskData.getKillData().getSkillCount() > 1){
                SendUtils.sendHegemonyResult(spritePlayerBean.getPlayerController(),settleTwo.getFirst(),worldMapTaskData.getKillData().getCurrentTotalScore(),
                        worldMapTaskData.getKillData().getVipPlus(),worldMapTaskData.getKillData().campScore(),settleTwo.getSecond());
            }
            //玩家在线通知玩家积分清0
            //推送争霸赛积分变化
            HegemonyScoreChangeBean changeBean = new HegemonyScoreChangeBean();
            changeBean.setScore(0);
            changeBean.setValue(0);
            changeBean.setChangeScore(0);
            changeBean.setType(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_EVENSKILL_VALUE);
            SendUtils.sendHegemoneyChange(spritePlayerBean.getPlayerController(), changeBean);
        }
        worldMapTaskData.getKillData().initCurrent();

        int afterValue = worldMapTaskData.getKillData().getMaxValue(E_WorldMapKillRankType.CURRENT_WEEK_RANK);
        //更新排行
        if (afterValue != beforeValue){
            GameServer.getInstance().getWorldManager().updateRankInfo(SGCommonProto.E_RANK_TYPE.RANK_TYPE_MAPCURRWEEK,
                    player, afterValue);
        }else{
            GameServer.getInstance().getWorldManager().updateRankPlayerDetail(player);
        }
    }



    /**
     * 大地图自动使用回复道具
     *
     */
    public static void checkAutoRecover(Player player, BattleTemp battleTemp, PlayerController playerController)
    {
        SettingInfo settings = player.getExtInfo(SettingInfo.class);
        AutoRecover autoRecover = settings.getAutoRecover();
        if (!autoRecover.enable) {
            // 自动恢复未开放
            return;
        }

        // 容错处理，避免死循环，最多加血4次
        for(int count = 0; count < 4 ;count++){
            // 自动使用次数是否已经超过上限
            if (autoRecover.autoUseTimes >= autoRecover.maxUseTimes) {
                return;
            }

            // 当前百分比
            int currentHpPercent = battleTemp.getPercent();
            if(currentHpPercent >= 100 || currentHpPercent > autoRecover.percent){
                return;
            }

            StableDataConfig stableDataConfig = DataFactory.getInstance().getGameObject(DataFactory.STABLE_DATA_KEY,
                    E_StableDataType.RECOVER_ITEM.getCode());
            BagInfo bagInfo = player.getExtInfo(BagInfo.class);
            GoodsData goodsData;
            int useHealthItemTimes = autoRecover.getUseTimes(ConstantFactory.PROP_TYPE_RECOVER);
            if (useHealthItemTimes >= stableDataConfig.goods.length) {
                goodsData = stableDataConfig.goods[stableDataConfig.goods.length - 1];
            } else {
                goodsData = stableDataConfig.goods[useHealthItemTimes];
            }

            // 道具数量是否足够
            if (goodsData != null) {
                if (bagInfo.getGoodsCount(SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_PROPS_VALUE,
                        goodsData.id) < goodsData.value) {
                    return;
                }
            }

            // 扣除资源
            bagInfo.subGoods(new GoodsData(SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_PROPS_VALUE, goodsData.id, goodsData.value));

            // 加血
            battleTemp.addHp(0.3d);

            // 增加道具总使用次数
            autoRecover.addUseTimes(ConstantFactory.PROP_TYPE_RECOVER);

            // 增加自动使用次数
            autoRecover.addAutoUseTime();

            if(playerController != null)
            {
                SendUtils.sendWorldMapUserPropInfo(playerController, ConstantFactory.PROP_TYPE_RECOVER, autoRecover.getUseTimes(ConstantFactory.PROP_TYPE_RECOVER));
            }
        }
    }




}
